package com.business.user.controller;


import com.alibaba.fastjson.JSONObject;
import com.business.common.dto.R;
import com.business.common.enums.BusinessExceptionEnum;
import com.business.common.enums.ErrorEnum;
import com.business.common.exception.CustomException;
import com.business.common.utils.StrKit;
import com.business.common.utils.SystemClock;
import com.business.redis.ExpiresTimeEnum;
import com.business.redis.constant.RedisKeyConstant;
import com.business.redis.utils.RedisUtil;
import com.business.user.annotation.FrequentRequest;
import com.business.user.annotation.TokenPermission;
import com.business.user.entity.User;
import com.business.user.entity.UserDto;
import com.business.user.service.UserService;
import com.business.user.utils.JWTUtil;
import com.business.user.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * 用户表: 后端controller类
 *
 * @author chenjiehong
 * @date 2019-04-28 15:03:18
 * @since 1.0
 */
@RestController
//@RequestMapping(value = "/user")
public class UserController {


    @Autowired
    private UserService userServiceImpl;

    /**
     * 手机注册用户
     *
     * @param params
     * @date 2019-04-28 15:03:18
     */
    @PostMapping("/register")
    public R register(@RequestBody JSONObject params) throws IOException {
        //校验验证码
        String validateCode = params.getString("validateCode");//手机验证码
        String realName = params.getString("realName");
        User user = params.toJavaObject(User.class);
        if (StrKit.isBlank(realName)) {
            return R.error(BusinessExceptionEnum.USER_NAME_NULL);
        }
        if (StrKit.isBlank(user.getPhone())) {
            return R.error(BusinessExceptionEnum.PHONE_NULL);
        }
        if (StrKit.isBlank(user.getPassword())) {
            return R.error(BusinessExceptionEnum.PASSWORD_NULL);
        }
        if (StrKit.isBlank(validateCode)) {
            return R.error(BusinessExceptionEnum.VERIFICATION_NUll);
        }
        UserUtil.validateCode(user.getPhone(), validateCode);

        User addR = userServiceImpl.add(user, realName);
        String token = JWTUtil.createJWT(ExpiresTimeEnum.REMEMBER_ME.getExpiresTime(), addR);
        token = addR.getId() + "." + token;//加上用户id
        addR.setToken(token);
        return R.success(addR);
    }


    /**
     * 登陆
     *
     * @param params
     * @date 2019-04-28 15:03:18
     */
    @PostMapping("/login")
    public R login(@RequestBody JSONObject params) throws IOException {

        String timestamp = params.getString("timestamp");
        if (StrKit.isBlank(timestamp)) {
            throw new CustomException(ErrorEnum.PARAMS_LOSE, "timestamp");
        }
        String key = String.format(RedisKeyConstant.USER_GET_CAPTCHA, timestamp);
        String redisCaptcha = (String) RedisUtil.getValue(key);
        String captcha = params.getString("captcha");

        if (redisCaptcha == null) {
            return R.error(BusinessExceptionEnum.VERIFICATION_CODE_OVERTIME);
        }
        if (StrKit.isBlank(captcha)) {
            return R.error(BusinessExceptionEnum.CAPTCHA_NULL);
        }
        if (!redisCaptcha.equals(captcha)) {
            return R.error(BusinessExceptionEnum.VERIFICATION_CODE_DIFFERENT);
        }
        User user = params.toJavaObject(User.class);
        User r = userServiceImpl.login(user, 0);
        boolean rememberMe = params.getBooleanValue("rememberMe");
        Long txpiresTime = null;
        if (rememberMe) {//记住我
            txpiresTime = ExpiresTimeEnum.REMEMBER_ME.getExpiresTime();
        } else {
            txpiresTime = ExpiresTimeEnum.LOGIN.getExpiresTime();
        }
        String token = JWTUtil.createJWT(txpiresTime, r);
        token = r.getId() + "." + token;//加上用户id
        r.setToken(token);
        return R.success(r);
    }


    /**
     * 退出登录
     *
     * @date 2019-04-28 15:03:18
     */
    @PostMapping("/logout")
    @TokenPermission
    public R logout(UserDto user) {
        String redisKey = String.format(RedisKeyConstant.USER_LOGIN_USER, user.getId());
        RedisUtil.delValue(redisKey);
        return R.success();
    }

    /**
     * 更新密码/重置密码 要先获取验证码
     *
     * @param params
     * @date 2019-04-28 15:03:18
     */
    @PostMapping("/updatePassword")
    @TokenPermission
    @FrequentRequest(5)//控制频繁操作 一分钟内可以操作5次
    public R updatePassword(@RequestBody JSONObject params, UserDto user) {
        //校验验证码
        String phone = params.getString("phone");//手机号码
        String verificationCode = params.getString("validateCode");//手机验证码
        UserUtil.validateCode(phone, verificationCode);

        if (!phone.equals(user.getPhone())) {
            return R.error(BusinessExceptionEnum.PHONE_INCONSISTENT);
        }
        String newPassword = params.getString("newPassword");
        String confirmPassword = params.getString("confirmPassword");
        return R.success(userServiceImpl.updatePassword(user.getId(), newPassword, confirmPassword));

    }

    /**
     * 更新手机号码
     *
     * @param params
     * @date 2019-04-28 15:03:18
     */
    @PostMapping("/updatePhone")
    @TokenPermission
    @FrequentRequest(5)//控制频繁操作 一分钟内可以操作5次
    public R updatePhone(@RequestBody JSONObject params, UserDto user) {
        Long phoneToken = params.getLong("phoneToken");
        if (phoneToken == null) {
            throw new CustomException(ErrorEnum.PARAMS_LOSE, "phoneToken");
        }
        //判断是否重复提交
        String phoneTokenKey =  String.format(RedisKeyConstant.USER_PHONE_TOKEN, user.getId());
        Long redisPhoneToken = (Long) RedisUtil.getValue(phoneTokenKey);
        if (redisPhoneToken == null || !redisPhoneToken.equals(phoneToken)) {
            return R.error(ErrorEnum.AUTH_ERROR);
        }
        //校验验证码
        String phone = params.getString("phone");//手机号码
        String verificationCode = params.getString("validateCode");//手机验证码
        UserUtil.validateCode(phone, verificationCode);

        Integer r = userServiceImpl.updatePhone(user.getId(), phone);
        RedisUtil.delValue(phoneTokenKey);
        RedisUtil.delValue( String.format(RedisKeyConstant.USER_GET_PHONE, user.getId()));
        return R.success(r);
    }


    /**
     * 获取手机号码
     *
     * @date 2019-04-28 15:03:18
     */
    @PostMapping("/getPhone")
    @TokenPermission
    @FrequentRequest(5)//控制频繁操作 一分钟内可以操作5次
    public R getPhone(UserDto user) {
        String key = String.format(RedisKeyConstant.USER_GET_PHONE, user.getId());
        if (!RedisUtil.hasKey(key)) {
            String r = userServiceImpl.getPhone(user.getId());
            RedisUtil.setValue(key, r, ExpiresTimeEnum.LEVEL_1.getExpiresTime());
            return R.success(r);
        } else {
            return R.success(RedisUtil.getValue(key));
        }
    }


    /**
     * 获取手机号码修改权限
     *
     * @date 2019-04-28 15:03:18
     */
    @PostMapping("/getPhoneToken")
    @TokenPermission
    @FrequentRequest(5)//控制频繁操作 一分钟内可以操作5次
    public R getPhoneToken(@RequestBody JSONObject params, UserDto user) {
        //校验验证码
        String phone = params.getString("phone");//手机号码
        R r = getPhone(user);
        if (!phone.equals(r.getData())) {
            return R.error(BusinessExceptionEnum.PHONE_INCONSISTENT);
        }
        String verificationCode = params.getString("validateCode");//手机验证码
        UserUtil.validateCode(phone, verificationCode);

        String key = String.format(RedisKeyConstant.USER_PHONE_TOKEN, user.getId());
        long token = SystemClock.now();
        RedisUtil.setValue(key, token, ExpiresTimeEnum.LEVEL_1.getExpiresTime());
        return R.success(token);
    }


}